package com.aaron.development.hangman.client;

import java.util.ArrayList;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.user.client.Random;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DecoratorPanel;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;

/** TODO Once the game has started remove the add/remove user options and just display
user info.

TODO When the start game button is selected show an input and select the user to choose 
the word.

TODO When the word has been entered and submited, rotate through the other users giving 
them guesses.

TODO Add click handlers like the one for wordSubmit
*/

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class HangMan implements EntryPoint {

	private VerticalPanel userPanel = new VerticalPanel();
	private VerticalPanel gamePanel = new VerticalPanel();
	private HorizontalPanel addPanel = new HorizontalPanel();
	private TextBox newUserTextBox = new TextBox();
	private Button addUserButton = new Button("Submit");
	private Button startGameButton = new Button("Start Game");
	private FlexTable userNamesTable = new FlexTable();
	private ArrayList<String> usernames = new ArrayList<String>();
	private HorizontalPanel mainPanel = new HorizontalPanel();
	private DecoratorPanel userHolder = new DecoratorPanel();
	private String hangManUser = new String();
	private TextBox hangManWord = new TextBox();
	private DialogBox userAndMessage = new DialogBox();

	
	/**
	 * This is the entry point method.
	 */
	public void onModuleLoad() {
		// Attach the user list to the decorator panel
		userHolder.setWidget(userPanel);		
		
		// Create section for adding users
		createPanelForUserAddition();
	    
		// Create section for game display
		createGameDisplay();
		
	    // Set the userPanel on the left side of the screen
		mainPanel.add(userHolder);
	    
	    // Set the right side of the screen
		mainPanel.add(gamePanel);
	    
	    // Attach the horizontal split widget to the display.
	    RootPanel.get("playerList").add(mainPanel);
	    
	    // Add the click listener to the addUserButton
	    eventHandlingForUserAddButton();

	    // Listen for keyboard events in the input box.
	    eventHandlingForUserNameKeyPress();
	}
	
	private void createGameDisplay() {
		// Create the start game button
		gamePanel.add(startGameButton);
		
		startGameButton.addClickHandler(startGameClick);
	}
	
	ClickHandler startGameClick = new ClickHandler() {
		@Override
		public void onClick(ClickEvent event) {
			if (usernames.size() > 1) {				
				// Remove the start button, might change this to just hide it
				startGameButton.setVisible(false);
				
				// Set up widgets and panels
				Button submitButton = new Button("Submit");
				Button closeDialogBox = new Button("Cancel");
				Label userToEnterWord = new Label(hangManUser + " is going to enter the word.");
				VerticalPanel dialogPanel = new VerticalPanel();
				HorizontalPanel dialogButtonPanel = new HorizontalPanel();
				
				// Set up title and animation for dialog box and center it
				userAndMessage.setText("Remote Procedure Call");
				userAndMessage.setAnimationEnabled(true);
				userAndMessage.center();
				
				// Add buttons to horizontal panel
				dialogButtonPanel.add(submitButton);
				dialogButtonPanel.add(closeDialogBox);
				
				// Add widgets to vertical panel
				dialogPanel.add(userToEnterWord);
				dialogPanel.add(hangManWord);
				dialogPanel.add(dialogButtonPanel);
				
				hangManWord.setText("Enter word here.");
				hangManUser = usernames.get( Random.nextInt(usernames.size()) );	
				
				// Add event handlers for buttons
				submitButton.addClickHandler(wordSubmit);
				closeDialogBox.addClickHandler(hideDialogBox);
				
				userAndMessage.setWidget(dialogPanel);								
				userAndMessage.show();
				
				// Set search box focus and select all
				hangManWord.setFocus(true);
				hangManWord.selectAll();
				
			    // Listen for keyboard events in the input box.
				hangManWord.addKeyPressHandler(enterSubmittedWord);
				
			} else {
				Window.alert("You need at least two users to play.");
			}
			
		}
		
	};
	
	ClickHandler hideDialogBox = new ClickHandler() {
		@Override
		public void onClick(ClickEvent event) {
			userAndMessage.hide();
			startGameButton.setVisible(true);
		}		
	};
	
	KeyPressHandler enterSubmittedWord = new KeyPressHandler() {
		public void onKeyPress(KeyPressEvent event) {
			if (event.getCharCode() == KeyCodes.KEY_ENTER) {
				handleSubmittedWord();
			}
		}		
	};
	
	ClickHandler wordSubmit = new ClickHandler() {
		public void onClick(ClickEvent event) {			
			handleSubmittedWord();
		}
	};
	
	private void handleSubmittedWord() {		
		String wordSubmitted = hangManWord.getText();
		// Make sure we have a word that is all characters
		if (! wordSubmitted.matches("^[a-zA-Z]+$") ) {
			Window.alert("This is not a valid word, try again.");
		} else {
			Window.alert("Congradulations, we are almost ready to being the game");
			// Create the world holder
			
		}		
	}
	
	private void createPanelForUserAddition() {
		// Create table do display users names
		userNamesTable.setText(0, 0, "Player Name");

	    // Assemble Add Stock panel.
	    addPanel.add(newUserTextBox);
	    addPanel.add(addUserButton);

	    // Assemble Main panel.
	    userPanel.add(userNamesTable);
	    userPanel.add(addPanel);		
	}
	
	private void eventHandlingForUserNameKeyPress() {
	    newUserTextBox.addKeyPressHandler(new KeyPressHandler() {
	      public void onKeyPress(KeyPressEvent event) {
	        if (event.getCharCode() == KeyCodes.KEY_ENTER) {
	          addUser();
	        }
	      }
	    });		
	}
	
	private void eventHandlingForUserAddButton() {
	    addUserButton.addClickHandler(new ClickHandler() {
	    	public void onClick(ClickEvent even) {
	    		addUser();
	    	}
	    });		
	}
	
	private void addUser() {
	    final String username = newUserTextBox.getText().toUpperCase().trim();
	    newUserTextBox.setFocus(true);

	    if (! setUserIfValid(username) ) return;

	    newUserTextBox.setText("");

	    // Don't add the username if it's already in the table.
	    if(usernames.contains(username))
	    	return;

	    // Add the username to the table.
	    int row = userNamesTable.getRowCount();
	    usernames.add(username);
	    userNamesTable.setText(row, 0, username);
	    
	    // Add a button to remove this username from the table.
	    createRemoveButtonForUser(username, row);

	}

	private void createRemoveButtonForUser(final String username, int row) {
	    Button removeUserButton = new Button("x");
	    removeUserButton.addClickHandler(new ClickHandler() {
	      public void onClick(ClickEvent event) {
	        int removedIndex = usernames.indexOf(username);
	        usernames.remove(removedIndex);
	        userNamesTable.removeRow(removedIndex + 1);
	      }
	    });
	    userNamesTable.setWidget(row, 1, removeUserButton);
	}
	
	private boolean setUserIfValid(String username) {
	    // username must be between 1 and 10 letters.
	    if (!username.matches("^[a-zA-Z\\.]{1,10}$")) {
	      Window.alert("'" + username + "' is not a valid username.");
	      newUserTextBox.selectAll();
	      return false;
	    }
	    
	    return true;
	}
	
}
